package com.lyn.plugin;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import com.lyn.plugin.cache.LruCache;
import com.lyn.plugin.entity.Plugin;
import com.lyn.plugin.proxy.ProxyActivity;

import java.io.File;

import dalvik.system.DexClassLoader;

/**
 * 插件管理器
 *
 * @author longyn 2022/11/30
 * @version 1.0.0
 */
public class PluginManager {

    /**
     * 插件加载缓存
     */
    public static LruCache<String, Plugin> pluginLruCache = new LruCache<>(1000);

    /**
     * 插件第一启动页
     */
    public static final int PLUGIN_LAUNCHER_CODE = 1;
    /**
     * 插件的其它普通页
     */
    public static final int PLUGIN_OTHER_CODE = 0;

    /**
     * 加载插件
     *
     * @param context 上下文
     * @param path    插件路径
     * @return Plugin
     */
    public static Plugin loadPlugin(Context context, String path) {
        if (TextUtils.isEmpty(path)) {
            throw new NullPointerException("path路径不能为空!");
        }
        if (!path.endsWith(".apk")) {
            throw new Error("只能加载apk文件!");
        }
        if (pluginLruCache.containsKey(path)) {
            return pluginLruCache.get(path);
        }
        PackageManager packageManager = context.getPackageManager();
        if (packageManager == null) {
            throw new NullPointerException("packageManager == null");
        }
        PackageInfo packageInfo = getPackageInfo(path, packageManager);
        Resources resources = getResources(packageManager, packageInfo);
        if (resources == null) {
            throw new NullPointerException("packageManager == null");
        }
        String packageName = packageInfo.packageName;
        if (TextUtils.isEmpty(packageName)) {
            throw new NullPointerException("packageName == null");
        }
        DexClassLoader dexClassLoader = new DexClassLoader(path
                , context.getCacheDir().getAbsolutePath()
                , null
                , context.getClassLoader());
        int pluginLauncherClassNameId = resources.getIdentifier("pluginLauncherClassName"
                , "string", packageName);
        String pluginLauncherClassName = resources.getString(pluginLauncherClassNameId);
        int pluginNameId = resources.getIdentifier("pluginName", "string", packageName);
        String pluginName = resources.getString(pluginNameId);
        int logoId = resources.getIdentifier("logo", "drawable", packageName);
        Drawable logoDrawable = resources.getDrawable(logoId);
        Plugin plugin = new Plugin.Builder()
                .setPackageName(packageName)
                .setName(pluginName)
                .setLogo(logoDrawable)
                .setLauncherClassName(pluginLauncherClassName)
                .setPath(path)
                .setResources(resources)
                .setClassLoader(dexClassLoader)
                .create();
        pluginLruCache.put(path, plugin);
        return plugin;
    }

    /**
     * 获取包信息
     *
     * @param path           插件路径
     * @param packageManager 包管理器
     * @return 包信息
     */
    private static PackageInfo getPackageInfo(String path, PackageManager packageManager) {
        PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path
                , PackageManager.GET_ACTIVITIES);
        packageInfo.applicationInfo.publicSourceDir = path;
        packageInfo.applicationInfo.sourceDir = path;
        return packageInfo;
    }

    /**
     * 获取插件Resources
     *
     * @param packageManager 包管理器
     * @param packageInfo    包信息
     * @return Resources
     */
    private static Resources getResources(PackageManager packageManager, PackageInfo packageInfo) {
        try {
            return packageManager.getResourcesForApplication(packageInfo.applicationInfo);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 取消加载插件
     *
     * @param path 插件路径
     */
    public static boolean unLoadPlugin(String path) {
        File file = new File(path);
        if (file.exists()){
            if (file.delete()){
                pluginLruCache.remove(path);
                return true;
            }
        }
        return false;
    }

    /**
     * 启动插件
     *
     * @param activity 当前activity
     * @param path     插件路径
     */
    public static void startPlugin(Activity activity, String path) {
        try {
            Intent intent = new Intent(activity, ProxyActivity.class);
            intent.putExtra("path", path);
            intent.putExtra("code", PLUGIN_LAUNCHER_CODE);
            activity.startActivity(intent);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动插件
     *
     * @param activity  当前activity
     * @param path      插件路径
     * @param className 插件类名
     */
    public static void startPlugin(Activity activity, String path, String className) {
        try {
            Intent intent = new Intent(activity, ProxyActivity.class);
            intent.putExtra("path", path);
            intent.putExtra("className", className);
            intent.putExtra("code", PLUGIN_OTHER_CODE);
            activity.startActivity(intent);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

}
